/***************************************************************************
 * The Open Armory API is a project to retrieve World of Warcraft(R)
 * related XML data from The Armory.
 *
 * The data retrieved via the Open Armory API from The Armory is
 * proprietary to Blizzard Entertainment, Inc(R).
 * *************************************************************************
 * Copyright (C) 2009 - 2010 Tedla M.B. Brandsema
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/
package net.openarmory.core.domain.validation;

import java.util.HashMap;
import java.util.Map;

import net.openarmory.core.domain.constants.CharacterClass;
import net.openarmory.core.domain.constants.CharacterRace;

import org.apache.log4j.Logger;

// TODO: Auto-generated Javadoc
/**
 * The Class RaceClassCombination.
 */
public final class RaceClassCombination {

	/** The Constant LOG. */
	private static final Logger LOG = Logger
			.getLogger(RaceClassCombination.class);

	/** The human class map. */
	private static final Map<Integer, Boolean> HUMAN_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The orc class map. */
	private static final Map<Integer, Boolean> ORC_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The dwarf class map. */
	private static final Map<Integer, Boolean> DWARF_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The night elf class map. */
	private static final Map<Integer, Boolean> NIGHT_ELF_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The undead class map. */
	private static final Map<Integer, Boolean> UNDEAD_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The tauren class map. */
	private static final Map<Integer, Boolean> TAUREN_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The gnome class map. */
	private static final Map<Integer, Boolean> GNOME_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The troll class map. */
	private static final Map<Integer, Boolean> TROLL_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The goblin class map. */
	private static final Map<Integer, Boolean> GOBLIN_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The blood elf class map. */
	private static final Map<Integer, Boolean> BLOOD_ELF_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The draenei class map. */
	private static final Map<Integer, Boolean> DRAENEI_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The worgen class map. */
	private static final Map<Integer, Boolean> WORGEN_CLASS_MAP = new HashMap<Integer, Boolean>();

	/** The race class map. */
	private static final Map<Integer, Map<Integer, Boolean>> RACE_CLASS_MAP = new HashMap<Integer, Map<Integer, Boolean>>();

	static {
		HUMAN_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		HUMAN_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), true);
		HUMAN_CLASS_MAP.put(CharacterClass.HUNTER.getNumericalRepresentation(),
				true);
		HUMAN_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		HUMAN_CLASS_MAP.put(CharacterClass.PRIEST.getNumericalRepresentation(),
				true);
		HUMAN_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		HUMAN_CLASS_MAP.put(CharacterClass.SHAMAN.getNumericalRepresentation(),
				false);
		HUMAN_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		HUMAN_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		HUMAN_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		HUMAN_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				false);

		ORC_CLASS_MAP.put(CharacterClass.WARRIOR.getNumericalRepresentation(),
				true);
		ORC_CLASS_MAP.put(CharacterClass.PALADIN.getNumericalRepresentation(),
				false);
		ORC_CLASS_MAP.put(CharacterClass.HUNTER.getNumericalRepresentation(),
				true);
		ORC_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		ORC_CLASS_MAP.put(CharacterClass.PRIEST.getNumericalRepresentation(),
				false);
		ORC_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		ORC_CLASS_MAP.put(CharacterClass.SHAMAN.getNumericalRepresentation(),
				true);
		ORC_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		ORC_CLASS_MAP.put(CharacterClass.WARLOCK.getNumericalRepresentation(),
				true);
		ORC_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		ORC_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				false);

		DWARF_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		DWARF_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), true);
		DWARF_CLASS_MAP.put(CharacterClass.HUNTER.getNumericalRepresentation(),
				true);
		DWARF_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		DWARF_CLASS_MAP.put(CharacterClass.PRIEST.getNumericalRepresentation(),
				true);
		DWARF_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		DWARF_CLASS_MAP.put(CharacterClass.SHAMAN.getNumericalRepresentation(),
				true);
		DWARF_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		DWARF_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		DWARF_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		DWARF_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				false);

		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), false);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.HUNTER.getNumericalRepresentation(), true);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.ROGUE.getNumericalRepresentation(), true);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.PRIEST.getNumericalRepresentation(), true);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.SHAMAN.getNumericalRepresentation(), false);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.MAGE.getNumericalRepresentation(), true);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), false);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.EMPTY.getNumericalRepresentation(), false);
		NIGHT_ELF_CLASS_MAP.put(
				CharacterClass.DRUID.getNumericalRepresentation(), true);

		UNDEAD_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		UNDEAD_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), false);
		UNDEAD_CLASS_MAP.put(
				CharacterClass.HUNTER.getNumericalRepresentation(), true);
		UNDEAD_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		UNDEAD_CLASS_MAP.put(
				CharacterClass.PRIEST.getNumericalRepresentation(), true);
		UNDEAD_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		UNDEAD_CLASS_MAP.put(
				CharacterClass.SHAMAN.getNumericalRepresentation(), false);
		UNDEAD_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		UNDEAD_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		UNDEAD_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		UNDEAD_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				false);

		TAUREN_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		TAUREN_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), true);
		TAUREN_CLASS_MAP.put(
				CharacterClass.HUNTER.getNumericalRepresentation(), true);
		TAUREN_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				false);
		TAUREN_CLASS_MAP.put(
				CharacterClass.PRIEST.getNumericalRepresentation(), true);
		TAUREN_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		TAUREN_CLASS_MAP.put(
				CharacterClass.SHAMAN.getNumericalRepresentation(), true);
		TAUREN_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				false);
		TAUREN_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), false);
		TAUREN_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		TAUREN_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				true);

		GNOME_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		GNOME_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), false);
		GNOME_CLASS_MAP.put(CharacterClass.HUNTER.getNumericalRepresentation(),
				false);
		GNOME_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		GNOME_CLASS_MAP.put(CharacterClass.PRIEST.getNumericalRepresentation(),
				true);
		GNOME_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		GNOME_CLASS_MAP.put(CharacterClass.SHAMAN.getNumericalRepresentation(),
				false);
		GNOME_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		GNOME_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		GNOME_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		GNOME_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				false);

		TROLL_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		TROLL_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), false);
		TROLL_CLASS_MAP.put(CharacterClass.HUNTER.getNumericalRepresentation(),
				true);
		TROLL_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		TROLL_CLASS_MAP.put(CharacterClass.PRIEST.getNumericalRepresentation(),
				true);
		TROLL_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		TROLL_CLASS_MAP.put(CharacterClass.SHAMAN.getNumericalRepresentation(),
				true);
		TROLL_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		TROLL_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		TROLL_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		TROLL_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				true);

		GOBLIN_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		GOBLIN_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), false);
		GOBLIN_CLASS_MAP.put(
				CharacterClass.HUNTER.getNumericalRepresentation(), true);
		GOBLIN_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		GOBLIN_CLASS_MAP.put(
				CharacterClass.PRIEST.getNumericalRepresentation(), true);
		GOBLIN_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		GOBLIN_CLASS_MAP.put(
				CharacterClass.SHAMAN.getNumericalRepresentation(), true);
		GOBLIN_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		GOBLIN_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		GOBLIN_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		GOBLIN_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				false);

		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.HUNTER.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.ROGUE.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.PRIEST.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.SHAMAN.getNumericalRepresentation(), false);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.MAGE.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.EMPTY.getNumericalRepresentation(), false);
		BLOOD_ELF_CLASS_MAP.put(
				CharacterClass.DRUID.getNumericalRepresentation(), false);

		DRAENEI_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), true);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.HUNTER.getNumericalRepresentation(), true);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.ROGUE.getNumericalRepresentation(), false);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.PRIEST.getNumericalRepresentation(), true);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.SHAMAN.getNumericalRepresentation(), true);
		DRAENEI_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), false);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.EMPTY.getNumericalRepresentation(), false);
		DRAENEI_CLASS_MAP.put(
				CharacterClass.DRUID.getNumericalRepresentation(), false);

		WORGEN_CLASS_MAP.put(
				CharacterClass.WARRIOR.getNumericalRepresentation(), true);
		WORGEN_CLASS_MAP.put(
				CharacterClass.PALADIN.getNumericalRepresentation(), false);
		WORGEN_CLASS_MAP.put(
				CharacterClass.HUNTER.getNumericalRepresentation(), true);
		WORGEN_CLASS_MAP.put(CharacterClass.ROGUE.getNumericalRepresentation(),
				true);
		WORGEN_CLASS_MAP.put(
				CharacterClass.PRIEST.getNumericalRepresentation(), true);
		WORGEN_CLASS_MAP.put(
				CharacterClass.DEATH_KNIGHT.getNumericalRepresentation(), true);
		WORGEN_CLASS_MAP.put(
				CharacterClass.SHAMAN.getNumericalRepresentation(), false);
		WORGEN_CLASS_MAP.put(CharacterClass.MAGE.getNumericalRepresentation(),
				true);
		WORGEN_CLASS_MAP.put(
				CharacterClass.WARLOCK.getNumericalRepresentation(), true);
		WORGEN_CLASS_MAP.put(CharacterClass.EMPTY.getNumericalRepresentation(),
				false);
		WORGEN_CLASS_MAP.put(CharacterClass.DRUID.getNumericalRepresentation(),
				true);

		RACE_CLASS_MAP.put(CharacterRace.HUMAN.getNumericalRepresentation(),
				HUMAN_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.ORC.getNumericalRepresentation(),
				ORC_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.DWARF.getNumericalRepresentation(),
				DWARF_CLASS_MAP);
		RACE_CLASS_MAP.put(
				CharacterRace.NIGHT_ELF.getNumericalRepresentation(),
				NIGHT_ELF_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.UNDEAD.getNumericalRepresentation(),
				UNDEAD_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.TAUREN.getNumericalRepresentation(),
				TAUREN_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.GNOME.getNumericalRepresentation(),
				GNOME_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.TROLL.getNumericalRepresentation(),
				TROLL_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.GOBLIN.getNumericalRepresentation(),
				GOBLIN_CLASS_MAP);
		RACE_CLASS_MAP.put(
				CharacterRace.BLOOD_ELF.getNumericalRepresentation(),
				BLOOD_ELF_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.DRAENEI.getNumericalRepresentation(),
				DRAENEI_CLASS_MAP);
		RACE_CLASS_MAP.put(CharacterRace.WORGEN.getNumericalRepresentation(),
				WORGEN_CLASS_MAP);
	}

	/**
	 * Instantiates a new race class combination.
	 */
	private RaceClassCombination() {

	}

	/**
	 * Validate race class combination.
	 * 
	 * @param race
	 *            the race
	 * @param clazz
	 *            the clazz
	 * @return true, if successful
	 */
	public static boolean validateRaceClassCombination(
			final CharacterRace race, final CharacterClass clazz) {
		final Map<Integer, Boolean> raceClassCombo = RACE_CLASS_MAP.get(race
				.getNumericalRepresentation());
		if (raceClassCombo != null) {
			return raceClassCombo.get(clazz.getNumericalRepresentation());
		}
		return false;
	}

	/**
	 * Prints the race class matrix.
	 */
	public static void printRaceClassMatrix() {
		final StringBuilder headers = new StringBuilder();
		headers.append(String.format("%-12s", ""));

		for (final CharacterClass clazz : CharacterClass.values()) {
			headers.append(String.format("%15s",
					clazz.getNumericalRepresentation() + "." + clazz));
		}

		System.out.println(headers);

		for (final CharacterRace race : CharacterRace.values()) {
			final StringBuilder row = new StringBuilder();
			row.append(String.format("%-12s", race.getNumericalRepresentation()
					+ "." + race));

			for (final CharacterClass clazz : CharacterClass.values()) {
				row.append(String.format("%15s",
						validateRaceClassCombination(race, clazz)));

			}
			System.out.println(row);
		}
	}
}
